using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Xml.XPath;
using System.Xml;
using Microsoft.Win32;

namespace MessengerQuotePlugin
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            formatBox.DataBindings.Add("Enabled", useFriendlyFormatBox, "Checked");

            loginBox.DisplayMember = "Id";
            loginBox.ValueMember = "Folder";
            List<HistoryInfo> historyInfos = GetHistoryPaths();
            if (historyInfos.Count == 0)
            {
                //error
                return;
            }

            loginBox.Items.AddRange(historyInfos.ToArray());
            if (loginBox.Items.Count > 0)
            {
                loginBox.SelectedIndex = 0;
            }
        }

        private void personsBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            progressBar.Visible = true;
            HistoryInfo info = loginBox.SelectedItem as HistoryInfo;
            if (info == null)
            {
                return;
            }
            string file = Path.Combine(info.Folder, personsBox.Text + ".xml");
            Enable(false);
            listView.BeginUpdate();
            listView.Items.Clear();
            listView.Groups.Clear();
            backgroundWorker.RunWorkerAsync(file);
        }

        public string GetQuote()
        {
            try
            {
                bool useFriendlyFormat = useFriendlyFormatBox.Checked;
                bool useColor = useColorBox.Checked;

                StringBuilder builder = new StringBuilder();
                if (!useFriendlyFormat)
                {
                    builder.Append(@"<table border=""0"" width=""100%"">");
                }
                foreach (ListViewItem item in listView.SelectedItems)
                {
                    string style = useColor ? string.Format(" style='color:{0};'", ColorTranslator.ToHtml(item.SubItems[4].ForeColor)) : string.Empty;
                    string format = useFriendlyFormat ? formatBox.Text.Replace("{4}", "<span" + style + ">{4}</span>") + "<br />" : "<tr><td width='10%' valign='top'>{0}</td><td width='10%' valign='top'>{1}</td><td width='10%' valign='top'>{2}</td><td width='10%' valign='top'>{3}</td><td" + style + " width='60%' valign='top'>{4}</td></tr>";
                    builder.AppendFormat(format, item.SubItems[0].Text, item.SubItems[1].Text, item.SubItems[2].Text, item.SubItems[3].Text, item.SubItems[4].Text);
                }
                if (!useFriendlyFormat)
                {
                    builder.Append(@"</table>");
                }
                return builder.ToString();
            }
            catch
            { 
                return "There was an error with quote generation. Please check your friendly formatting template. Friendly formatting template supports only parameters {0} through {4}";
            }
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = backgroundWorker.IsBusy;
        }

        private void listView_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            okButton.Enabled = listView.SelectedItems.Count > 0;
        }

        private void Enable(bool isEnabled)
        {
            okButton.Enabled = isEnabled ? listView.SelectedItems.Count > 0 : false;
            cancelButton.Enabled = isEnabled;
            loginBox.Enabled = isEnabled;
            personsBox.Enabled = isEnabled;
        }

        private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            string file = e.Argument as string;
            int currentSssion = -1;
            ListViewGroup group = null;
            XPathDocument document = new XPathDocument(file);
            XPathNavigator navigator = document.CreateNavigator();

            XPathNodeIterator messages = navigator.Select("Log/Message");
            int messageCount = messages.Count;
            int currentMessage = 0;

            while (messages.MoveNext())
            {
                Item item = new Item(messages.Current);
                if (currentSssion != item.Session)
                {
                    currentSssion = item.Session;
                    group = new ListViewGroup("Session " + currentSssion);
                }
                ListViewItem listItem = new ListViewItem(new string[]
                    {
                        item.DateTime.ToShortDateString(),
                        item.DateTime.ToShortTimeString(),
                        item.From, 
                        item.To,
                        item.Message
                    });
                listItem.UseItemStyleForSubItems = false;
                listItem.SubItems[4].ForeColor = item.Color;
                group.Items.Add(listItem);
                int percent = ++currentMessage * 100 / messageCount;
                backgroundWorker.ReportProgress(percent, listItem);
            }
            e.Result = true;
        }

        private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            try
            {
                ListViewItem item = e.UserState as ListViewItem;
                if (item != null)
                {
                    ListViewGroup group = listView.Groups[item.Group.ToString()];
                    if (group == null)
                    {
                        listView.Groups.Add(item.Group);
                    }
                    listView.Items.Add(item);
                }
                if (progressBar.Value != e.ProgressPercentage)
                {
                    progressBar.Value = e.ProgressPercentage;
                    progressBar.Refresh();
                }

                if (listView.Items.Count % 100 == 0)
                {
                    listView.EndUpdate();
                    listView.BeginUpdate();
                }
            }
            catch (Exception ex)
            { 
                MessageBox.Show(ex.ToString());
            }
        }

        private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            progressBar.Refresh();
            listView.AutoResizeColumn(4, ColumnHeaderAutoResizeStyle.ColumnContent);
            listView.EndUpdate();
            progressBar.Visible = false;
            progressBar.Value = 0;
            Enable(true);
        }

        private List<HistoryInfo> GetHistoryPaths()
        {
            List<HistoryInfo> historyPaths = new List<HistoryInfo>();

            string passportSettingspath = "Software\\Microsoft\\MSNMessenger\\PerPassportSettings";
            RegistryKey key = Registry.CurrentUser.OpenSubKey(passportSettingspath);
            if (key == null)
            {
                return historyPaths;
            }

            string[] subKeyNames = key.GetSubKeyNames();
            foreach (string idKey in subKeyNames)
            {
                RegistryKey historyKey = Registry.CurrentUser.OpenSubKey(passportSettingspath + "\\" + idKey);
                if (historyKey != null)
                {
                    string historyPath = historyKey.GetValue("MessageLogPath") as string;
                    if (historyPath != null && historyPath.Length > 0)
                    {
                        string idName = GetIdName(idKey, historyPath);
                        HistoryInfo info = new HistoryInfo(idName, historyPath);
                        historyPaths.Add(info);
                    }
                }
            }
            return historyPaths;
        }

        private string GetIdName(string id, string path)
        {
            string pattern = @"(?<=\\)[^\\]*?(?=" + id + @"\\)";
            string name = System.Text.RegularExpressions.Regex.Match(path, pattern).Value;
            if (name.Length == 0)
            {
                name = id;
            }
            return name;
        }

        private void loginBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            HistoryInfo info = loginBox.SelectedItem as HistoryInfo;
            if (info == null)
            {
                return;
            }

            string[] files = Directory.GetFiles(info.Folder, "*.xml");

            personsBox.Items.Clear();
            foreach (string file in files)
            {
                personsBox.Items.Add(Path.GetFileNameWithoutExtension(file));
            }
            if (personsBox.Items.Count > 0)
            {
                personsBox.SelectedIndex = 0;
            }
        }
    }
}